package com.game.manager.security;

import java.io.IOException;
import javax.annotation.PostConstruct;
import javax.servlet.http.HttpServletResponse;

import com.game.manager.service.GmAccountService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.builders.WebSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
import org.springframework.security.web.csrf.HttpSessionCsrfTokenRepository;
import org.springframework.security.web.util.matcher.AntPathRequestMatcher;
import com.alibaba.fastjson.JSONObject;

@EnableWebSecurity
@Configuration
public class GmSecurityConfig extends WebSecurityConfigurerAdapter {
    private Logger logger = LoggerFactory.getLogger(GmSecurityConfig.class);
    @Autowired
    private ApplicationContext appContext;
    @Autowired
    private GmAccountService accountService;

    @PostConstruct
    public void init() {
        Object bean = appContext.getBean("springSecurityFilterChain");
        logger.info("Bean 名字：{}", bean.getClass().getName());
    }

    @Override
    public void configure(WebSecurity web) throws Exception {
        // 把静态资源和登陆页面忽略掉，不进行权限验证
        web.ignoring().antMatchers("/favicon.ico", "/layout/index", "/gm/easyui/**", "/gm/layui/**", "/gm/server-option/**", "/gm/jquery.min.js", "/images/**");//, "/account/**", "/menu/**", "/gm-role/**", "/gm-role/**"
    }

    @Override
    protected void configure(HttpSecurity httpSecurity) throws Exception {
        HttpSessionCsrfTokenRepository csrfTokenRepository = new HttpSessionCsrfTokenRepository();
        //重命令存储session时的key的名字，默认的名字太长了
        csrfTokenRepository.setSessionAttributeName("_csrf");

        httpSecurity
                .formLogin().loginPage("/layout/index") // 设置登陆页面
                .loginProcessingUrl("/account/login") // 设置处理登陆提交的path
                .and().authorizeRequests().anyRequest().authenticated()// 所有的请求都登陆后才可以访问
                .and().headers().frameOptions().sameOrigin() // 防止iframe页面加载失败
                //.and().csrf().disable()
                .and().csrf()
                .ignoringAntMatchers("/account/login", "/menu/**", "/layout/**", "/gm-role/**")
                .csrfTokenRepository(csrfTokenRepository);
        // 替换过滤器
        AjaxJsonUsernamePasswordAuthenticationFilter ajaxJsonLoginFilter = new AjaxJsonUsernamePasswordAuthenticationFilter();
        ajaxJsonLoginFilter.setRequiresAuthenticationRequestMatcher(new AntPathRequestMatcher("/account/login", "POST"));
        // 配置认证类
        GmAuthenticationManager authenticationManager = new GmAuthenticationManager(accountService);
        ajaxJsonLoginFilter.setAuthenticationManager(authenticationManager);
        //处理认证成功之后的返回
        ajaxJsonLoginFilter.setAuthenticationSuccessHandler((request, response, authentication) -> {
            JSONObject data = new JSONObject();
            data.put("code", 0);
            data.put("msg", "登陆成功");
            this.response(response, data);
        });
        //处理认证失败之后的返回
        ajaxJsonLoginFilter.setAuthenticationFailureHandler((request, response, exception) -> {
            JSONObject data = new JSONObject();
            data.put("code", -1);
            data.put("msg", "登陆失败:" + exception.getMessage());
            this.response(response, data);
        });
        // 替换掉旧的登陆处理过滤器
        httpSecurity.addFilterAt(ajaxJsonLoginFilter, UsernamePasswordAuthenticationFilter.class);
    }
    //返回数据
    private void response(HttpServletResponse response, JSONObject data) {
        String str = data.toJSONString();
        try {
            response.getOutputStream().write(str.getBytes("utf8"));
            response.getOutputStream().flush();
        } catch (IOException e) {
           logger.error("数据返回错误",e);
        }
    }


}
